using System.IdentityModel.Tokens.Jwt;
using System.Text;
using KL.Core.Common.MyOptions;
using KL.Core.Common.Utils;
using KL.Standard.Domain.MessageQueue;
using KL.Standard.Domain.Services;
using KL.Standard.Model.Infrastructure;
using KL.Standard.Model.ViewModels.InParams;
using KL.Standard.Model.ViewModels.Queue;
using KL.Standard.RabbitMQ;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;

namespace EagCentralPlatform.Net8.Controllers.BaseArch;

[Route("sys")]
[ApiController]
public class SystemController : BaseApiController
{

    private readonly IUserSvc _userSvc;

    private readonly IConfiguration _configuration;

    private readonly AppCustomParaOptions _configs;
    private readonly RabbitMqOptions _qmConfigs;
    private readonly JwtConfigOptions _jwtConfig;
    public SystemController(IUserSvc userSvc, 
        IConfiguration configuration,
        IOptions<AppCustomParaOptions> options,
        IOptions<RabbitMqOptions> options2,
        IOptions<JwtConfigOptions> options3)
    {
        _userSvc = userSvc;

        _configuration = configuration;
        _configs = options.Value;
        _qmConfigs = options2.Value;
        _jwtConfig = options3.Value;
    }
    #region 登录

    /// <summary>
    /// 登录（版本2，兼容 .net framework）
    /// </summary>
    /// <param name="p"></param>
    /// <returns></returns>
    [AllowAnonymous]
    [HttpPost("login")]
    public BaseResult<CurUserInfo> LoginV2([FromBody] LoginParam p)
    {
        //_log.Debug("invoke /sys/login:" + p);
        //string serializeToken = null;
        if (!ModelState.IsValid)
        {
            return new BaseResult<CurUserInfo>()
            {
                success = false,
                error = "参数有误！",
            };
        }

        BaseResult<CurUserInfo> res = _userSvc.Login(p);
        if (!res.success)
        {
            return res;
        }
        else
        {
            res.data.lang = p.lang;
            // STEP0: 在当前账号密钥中做下登记
            res.data.cKey = Guid.NewGuid().ToString("N");
            // int count = _userRepository.Login2Key(res.data);
            // if (count > 0)
            // {
            //     var systems = _subSystemRepository.GetSubSystems4LoginID(res.data.loginID);
            //     res.data.systems = systems;
            // STEP1: 建立使用者的 Claims 聲明，這會是 JWT Payload 的一部分
            var userClaims = ClaimUtils.CreateClaimInfos<CurUserInfo>(res.data);
            var jwtConfig = _jwtConfig;
            // STEP2: 取得對稱式加密 JWT Signature 的金鑰
            // 這部分是選用，但此範例在 Startup.cs 中有設定 ValidateIssuerSigningKey = true 所以這裡必填
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.securityKey));
            // STEP3: 建立 JWT TokenHandler 以及用於描述 JWT 的 TokenDescriptor
            var tokenHandler = new JwtSecurityTokenHandler();
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Issuer = jwtConfig.issuser,
                Audience = jwtConfig.audience,
                Subject = userClaims,
                Expires = DateTime.Now.AddHours(jwtConfig.expiresHour),
                SigningCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256)
            };
            // 產出所需要的 JWT Token 物件
            var securityToken = tokenHandler.CreateToken(tokenDescriptor);
            // 產出序列化的 JWT Token 字串
            res.data.aToken = tokenHandler.WriteToken(securityToken);
            res.error = "登录验证成功！";
            return res;


        }
    }

    #endregion
    
    #region 测试队列模式
    /// <summary>
    /// 测试队列模式
    /// </summary>
    /// <param name="cType"></param>
    /// <returns></returns>
    [AllowAnonymous]
    [HttpPost("testmq/{cType}/{msg}")]
    public BaseResult<string> TestMq(string cType ,string msg,[FromServices]IServiceProvider provider)
    {
        if (!_qmConfigs.Enabled)
        {
            return new BaseResult<string>() { success = false,error = "当前系统未开启[RabbitMQ]消息队列服务！"};
        }

        using (var scope = provider.CreateScope())
        {
            var queueProductor = scope.ServiceProvider.GetService<IBaseQueueProductor<BASEMQ>>();
            if (cType.ToLower().Equals("direct"))
                queueProductor.PublishMsg(new MQueueItem<string>() { data = $"{msg}_direct" },
                    $"{_configs.SYS_CODE}_QUEUE_NAME", _configs.SYS_CODE, "Direct_Exchg_NET8");
            else if (cType.ToLower().Equals("fanout"))
            {
                queueProductor.BroadcastMsg(new MQueueItem<string>() { data = $"{msg}_fanout" },
                    new string[]
                    {
                        $"{_configs.SYS_CODE}_QUEUE_NAME"
                    }.ToList(), "Fanout_Exchg_NET8");
            }
        }
        return new BaseResult<string>() { success = true };
    }
    #endregion
}